package com.szxx.suit.threetakepairplus;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.szxx.constant.DdzCardTypes;
import com.szxx.constant.DdzCardConstant;
import com.szxx.domain.Card;
import com.szxx.domain.Cards;
import com.szxx.domain.DdzCard;
import com.szxx.suit.AbstractSuitTerm;
import com.szxx.suit.AbstractSuitType;
import com.szxx.suit.DdzAnalysisResult;
import com.szxx.suit.DdzSuitAnalyzer;
import com.szxx.suit.DdzTypeUtil;
import com.szxx.suit.fourtakepair.FourTakePairTypeAnalyzer;
import com.szxx.suit.three.ThreeTypeAnalyzer;
import com.szxx.suit.threestraight.ThreeStraightTypeAnalyzer;
import com.szxx.util.PokerUtil;

/**
 * 三带二飞机 <br>
 *
 * @author Ambrose
 */
@Component
public class ThreeTakePairPlusTypeAnalyzer extends DdzSuitAnalyzer {
	
	@Autowired
	private FourTakePairTypeAnalyzer fourTakePairTypeAnalyzer;

	@Override
	public AbstractSuitType getSuitType() {
		return DdzCardTypes.THREE_TAKE_PAIR_PLUS;
	}

	/** 关键数量 */
	private static int LIMIT_SIZE = 10;
	
	/** 关键数量 */
	private static int TUPLE_SIZE = 5;
	
	@Override
	protected boolean doCheckRule(Cards cards, AbstractSuitTerm term, DdzAnalysisResult result) {
		if (result.getCardNum() >= LIMIT_SIZE && result.getCardNum() % TUPLE_SIZE == 0) {
			if (result.isAllCardLazi()) { // 全部癞子默认炸弹
				return false;
			}
			List<Integer> allValues = result.getNoneLaziValueCounter().getAllValues();
			if (allValues.size() == 1) { // 3*******  5555*** 默认炸弹
				return false;
			}
			if (result.getNoneLaziValueCounter().hasJoker()) { // 非赖部分有王
				return false;
			}
			int tupleNum = result.getCardNum() / TUPLE_SIZE; // 分析有几组牌，三带一对算做一组
			if (allValues.size() > tupleNum << 2) { 
				// 考虑情况 3334445555  和  33344455566677778888
				return false;
			}
			// 遍历寻找所有可能的顺子
			for (int beginValueTemp = DdzCardConstant.NUMBER_2_VALUE - 1 // 从A开始
					; beginValueTemp >= DdzCardConstant.NUMBER_3_VALUE + (tupleNum - 1); beginValueTemp--) {
				int beginValueTempNum = result.getNoneLaziValueCounter().getValueCount(beginValueTemp);
				// 三带二中飞机里，出现四次的点数不会出现在顺子中
				if (beginValueTempNum < 4 && DdzTypeUtil.ensureStaight(beginValueTemp, TUPLE_SIZE, 
						ThreeStraightTypeAnalyzer.TUPLE_SIZE, cards, term, result)) { 
					int allNeedLaiziCardNum = 0;
					HashSet<Integer> straightValues = new HashSet<Integer>();
					for (int valueTemp = beginValueTemp; valueTemp > beginValueTemp - tupleNum; valueTemp--) { // 从大到小
						straightValues.add(valueTemp);
						int valueTempNum = result.getNoneLaziValueCounter().getValueCount(valueTemp);
						int needLaziNum = ThreeStraightTypeAnalyzer.TUPLE_SIZE - valueTempNum;
						needLaziNum = needLaziNum > 0 ? needLaziNum : 0; // 防止出现负数
						allNeedLaiziCardNum += needLaziNum;
					}
					for (Integer valueTemp : allValues) {
						if (!straightValues.contains(valueTemp) 
								&& result.getNoneLaziValueCounter().getValueCount(valueTemp) % 2 != 0) {
							allNeedLaiziCardNum++;
						}
					}
					if (result.getLaziCardNum() >= allNeedLaiziCardNum) {
						return true;
					}
				}
			}
			return false;
		} else {
			return false;
		}
	}
	
	@Override
	protected List<Cards> doAnalysizeLaizi(Cards cards, AbstractSuitTerm term, boolean onlyMaxValue) {
		List<Cards> cardsResult = new LinkedList<Cards>();
		DdzAnalysisResult result = (DdzAnalysisResult) cards.getResult();
		List<Card> laiziCardList = new ArrayList<Card>(cards.subList(result.getCardNum() - result.getLaziCardNum(), result.getCardNum()));
		List<Integer> allValues = result.getNoneLaziValueCounter().getAllValues();
		int laiziCardNum = result.getLaziCardNum();
		int tupleNum = result.getCardNum() / TUPLE_SIZE; // 分析有几组牌，三带一算做一组
		for (int beginValueTemp = DdzCardConstant.NUMBER_2_VALUE - 1 // 从A开始
				; beginValueTemp >= DdzCardConstant.NUMBER_3_VALUE + (tupleNum - 1); beginValueTemp--) {
			int beginValueTempNum = result.getNoneLaziValueCounter().getValueCount(beginValueTemp);
			// 三带二中飞机里，出现四次的点数不会出现在顺子中
			if (beginValueTempNum < 4 && DdzTypeUtil.ensureStaight(beginValueTemp, TUPLE_SIZE, 
					ThreeStraightTypeAnalyzer.TUPLE_SIZE, cards, term, result)) {
				int allNeedLaiziCardNum = 0;
				int laiziCardIndex = 0;
				HashSet<Integer> straightValues = new HashSet<Integer>();
				for (int valueTemp = beginValueTemp; valueTemp > beginValueTemp - tupleNum; valueTemp--) { // 从大到小
					result.setSortFirstValue(valueTemp); // 随着循环确定从哪里开始顺
					straightValues.add(valueTemp);
					int valueTempNum = result.getNoneLaziValueCounter().getValueCount(valueTemp);
					int needLaziNum = ThreeStraightTypeAnalyzer.TUPLE_SIZE - valueTempNum;
					needLaziNum = needLaziNum > 0 ? needLaziNum : 0; // 防止出现负数
					allNeedLaiziCardNum += needLaziNum;
					for (int i = 0; i < needLaziNum; i++) {
						((DdzCard)laiziCardList.get(laiziCardIndex++)).changeCard(valueTemp);
					}
				}
				for (Integer valueTemp : allValues) {
					if (!straightValues.contains(valueTemp) 
							&& result.getNoneLaziValueCounter().getValueCount(valueTemp) % 2 != 0) { // 数量为奇数数牌补成对子
						allNeedLaiziCardNum++;
						if (allNeedLaiziCardNum <= laiziCardNum) {
							((DdzCard)laiziCardList.get(laiziCardIndex++)).changeCard(valueTemp);
						} else {
							break;
						}
					}
				}
				for (int i = laiziCardIndex; i < laiziCardList.size(); i++) { // 如果有剩余癞子组合成对
					((DdzCard)laiziCardList.get(i)).changeCard(laiziCardList.get(laiziCardIndex).getNumber());
				}
				if (allNeedLaiziCardNum <= laiziCardNum) {
					Cards cardsCopy = cards.clone();
					analysize(cardsCopy, term);
					cardsResult.add(cardsCopy);
					if (onlyMaxValue) {
						break; // 取完最大一组就跳出
					}
				}
			}
		}
		return cardsResult;
	}
	
	/**
	 * 飞机中 4张的点数会对排序造成影响
	 */
	@Override
	protected void sort(Cards cards, AbstractSuitTerm term) {
		PokerUtil.sortCards_asc(cards);
		DdzAnalysisResult result = (DdzAnalysisResult) cards.getResult();
		List<Card> cardlist = cards.getCardList();
		List<Card> sortCardList = new ArrayList<Card>(result.getCardNum());
		int firstSortValue = result.getSortFirstValue();
		int tupleNum = result.getCardNum() / TUPLE_SIZE; // 分析有几组牌，三带一算做一组
		for (int valueTemp = firstSortValue; valueTemp < firstSortValue + tupleNum; valueTemp++) { // 把三顺排好序
			int count = 0;
			for (Iterator<Card> iterator = cardlist.iterator(); iterator.hasNext();) {
				Card card = iterator.next();
				if (card.getValue() == valueTemp) {
					sortCardList.add(card);
					iterator.remove();
					count++;
					if (count == 3) { // 只要三张
						break;
					}
				}
			}
		}
		cardlist.addAll(0, sortCardList);
	}
	
	@Override
	protected boolean containsPossibleCards(Cards handCards, AbstractSuitTerm term) {
		DdzAnalysisResult result = (DdzAnalysisResult) handCards.getResult();
		if (result.getCardNum() - result.getJokerCardNum() < LIMIT_SIZE) { // 张数不够
			return false;
		}
		// 遍历寻找所有可能的顺子
		for (int beginValueTemp = DdzCardConstant.NUMBER_2_VALUE - 1 // 从A开始
				; beginValueTemp >= DdzCardConstant.NUMBER_3_VALUE + LIMIT_SIZE / TUPLE_SIZE - 1; beginValueTemp--) {
			if (DdzTypeUtil.ensureTupleStaightDesc(
					beginValueTemp, LIMIT_SIZE / TUPLE_SIZE, ThreeTypeAnalyzer.TUPLE_SIZE, handCards, term, result)) { // 最低标准顺一下
				return true;
			}
		}
		return false;
	}
	
	/** 最多使用癞子的数量 */
	private static int MAX_USE_LAIZI_CARD_NUM = 8;
	
	/** 防重复判定的比例值 参照 int key = tupleNum * TUPLE_WEIGHT + beginValueTemp; */
	private static int TUPLE_WEIGHT = 1000000;
	
	/** 癞子权重，区分癞子变成的5 和 原本就是5 */
	private static int LAIZI_WEIGHT = 1000;
	
	@Override
	protected List<Cards> doListPossibleCards(Cards handCards, AbstractSuitTerm term) {
		List<Cards> cardsResult = new LinkedList<Cards>();
		// 非癞子部分
		DdzAnalysisResult result = (DdzAnalysisResult) handCards.getResult();
		List<Card> noneLaiziCardList = handCards.subList(0, result.getNoneCardNum());
		Cards noneLaiziCards = DdzTypeUtil.createCardsCopy(noneLaiziCardList);
		noneLaiziCards.setResult(handCards.getResult().clone());
		DdzAnalysisResult noneLaiziCardsResult = (DdzAnalysisResult) noneLaiziCards.getResult();
		noneLaiziCardsResult.collectNumber(noneLaiziCards, term);
		// 癞子部分
		List<Card> laiziCardList = handCards.subList(result.getNoneCardNum(), result.getCardNum());
		Cards laiziCards = DdzTypeUtil.createCardsCopy(laiziCardList);
		laiziCards.setResult(handCards.getResult().clone());
		
		int laiziCardNum = result.getLaziCardNum();
		int maxUseLaiziCardNum = MAX_USE_LAIZI_CARD_NUM < laiziCardNum ? MAX_USE_LAIZI_CARD_NUM : laiziCardNum;
		Set<Integer> exsitKeys = new HashSet<Integer>();
		for (int useLaiziCardNum = 0; useLaiziCardNum <= maxUseLaiziCardNum; useLaiziCardNum++) { // 补几张癞子
			// 从5顺开始找 10.JQK1 找完找 9.10.J.Q.K.1 在找 8.9.10.J.Q.K.1 
			for (int tupleNum = LIMIT_SIZE / TUPLE_SIZE
					; tupleNum <= (noneLaiziCardsResult.getCardNum() + useLaiziCardNum) / TUPLE_SIZE; tupleNum++) {
				LinkedList<Cards> partLenResult = new LinkedList<Cards>(); // 部分长度的结果 
				// 遍历寻找所有可能的顺子  10.J.Q.K.1 找完找 9.10.J.Q.K 在找 8.9.10.J.Q
				for (int beginValueTemp = DdzCardConstant.NUMBER_2_VALUE - 1 // 从A开始
						; beginValueTemp >= DdzCardConstant.NUMBER_3_VALUE + tupleNum - 1; beginValueTemp--) {
					Cards modelCardsCopy = noneLaiziCards.clone(); // 常规牌副本
					DdzAnalysisResult modelResultCopy = (DdzAnalysisResult) modelCardsCopy.getResult();
					List<Card> useLaiziCardsCopy = DdzTypeUtil.cloneSublistedCards(laiziCards, 0, useLaiziCardNum); // 癞子副本
					Collections.reverse(useLaiziCardsCopy); // 因为这里是倒序赋值，避免 把点数小的癞子牌赋成大值又把点数大的癞子牌赋成小值 的疑惑
					Cards checkCards = DdzTypeUtil.cloneCardsAndAddCardList(modelCardsCopy, useLaiziCardsCopy); // 常规牌补上癞子，用于校验顺子
					DdzAnalysisResult checkResult = (DdzAnalysisResult) checkCards.getResult();
					checkResult.collectNumber(checkCards, term); // 收集下信息
					int straightKey = tupleNum * TUPLE_WEIGHT + beginValueTemp;
					if (!exsitKeys.contains(straightKey) // 每种顺子仅判定一次
							&& DdzTypeUtil.ensureTupleStaightDesc(beginValueTemp, tupleNum, ThreeTypeAnalyzer.TUPLE_SIZE, checkCards, term, checkResult)) {
						exsitKeys.add(straightKey);
						Cards tupleCards = new Cards();
						int firstSortValue = -1;
						for (int valueTemp = beginValueTemp; valueTemp > beginValueTemp - tupleNum; valueTemp--) { // 从大到小
							firstSortValue = valueTemp;
							int valueTempNum = modelResultCopy.getNoneLaziValueCounter().getValueCount(valueTemp);
							if (valueTempNum >= ThreeTypeAnalyzer.TUPLE_SIZE) {
								List<Card> removedCardList = DdzTypeUtil.cloneRemovedCards(modelCardsCopy, valueTemp, ThreeTypeAnalyzer.TUPLE_SIZE);
								tupleCards.addCards(removedCardList);
							} else {
								List<Card> removedCardList = DdzTypeUtil.cloneRemovedCards(modelCardsCopy, valueTemp, valueTempNum);
								int needLaiziCardNum = ThreeTypeAnalyzer.TUPLE_SIZE - valueTempNum;
								for (int i = 0; i < needLaiziCardNum; i++) { // 用了癞子才加上，不会任意补全（癞子不会去替代玩家已有的顺子中的元素）
									DdzCard laiziCardCopy = (DdzCard) useLaiziCardsCopy.remove(0);
									laiziCardCopy.changeCard(valueTemp);
									removedCardList.add(laiziCardCopy);
								}
								tupleCards.addCards(removedCardList);
							}
						}
						// 是否所有头部顺子都是癞子 ******带56，去重
						boolean isAllTupleCardLaiz = true;
						for (Card tupleCard : tupleCards) {
							if (!((DdzCard)tupleCard).isLazi()) {
								isAllTupleCardLaiz = false;
							}
						}
						Cards remainCards = DdzTypeUtil.cloneCardsAndAddCardList(modelCardsCopy, useLaiziCardsCopy);
						// 寻找相应的几张单牌
						List<Cards> takenCardsList = fourTakePairTypeAnalyzer.repeatSelectPairCards(remainCards, tupleNum, term);
						List<Cards> subPartLenResult = new LinkedList<Cards>(); // 部分长度的结果 
						for (Cards takenCards : takenCardsList) {
							Cards resultCards = DdzTypeUtil.cloneCardsAndAddCards(tupleCards, takenCards);
							int resultKey = tupleNum * TUPLE_WEIGHT;
							if (isAllTupleCardLaiz) {
								resultKey += TUPLE_WEIGHT >> 2; // 这里随便给个值表示头部全是癞子 
								for (Card card : takenCards) {
									if (((DdzCard)card).isLazi()) { // 癞子权重，区分癞子变成的5 和 原本就是5
										resultKey += card.getValue() * LAIZI_WEIGHT;
									} else {
										resultKey += card.getValue();
									}
								}
							} else {
								for (Card card : resultCards) {
									if (((DdzCard)card).isLazi()) { // 癞子权重，区分癞子变成的5 和 原本就是5
										resultKey += card.getValue() * LAIZI_WEIGHT;
									} else {
										resultKey += card.getValue();
									}
								}
							}
							if (!exsitKeys.contains(resultKey) 
									&& match(resultCards, term)) {
								exsitKeys.add(resultKey);
								// 保证排序
								((DdzAnalysisResult)resultCards.getResult()).setSortFirstValue(firstSortValue);
								analysize(resultCards, term);
								subPartLenResult.add(resultCards);
							}
						}
						partLenResult.addAll(0, subPartLenResult); // 这里要逆序保证小的在前面
					}
				}
				cardsResult.addAll(partLenResult);
			}
		}
		return cardsResult;
	}

}
